#include "./Include/CBoostLog.h"
#include <boost/bind/bind.hpp>

CBoostLog::CBoostLog()
:isStoped(false)
{}

CBoostLog::~CBoostLog() 
{
	StopLog();
}

//初始化日志相关信息
void CBoostLog::InitLog(const std::string& log_root, const logging::formatter &fmt, unsigned int save_days)
{
    std::string logDir = log_root + "/log";

    /*******************initialize sinks*********************/
    //检查文件夹
    std::string logSubDir = logDir + "/Info/";
    if (!filesys::exists(logSubDir))
        filesys::create_directories(logSubDir);
    //后端sink
    boost::shared_ptr<sinks::text_file_backend> back_end_normal =
        boost::make_shared<sinks::text_file_backend>(
            keywords::file_name = "normal.log",                                                //文件名
            keywords::target_file_name = "normal_%Y%m%d_%3N.log",                                  //翻转后的文件名,normal_20201202.log
            keywords::rotation_size = 1024 * 1024 * 1024,                                       //输出文件大小
            keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0),      //翻转时间[0:0:0]
            keywords::auto_flush = "true",                                                     //文件内容实时刷新
            keywords::open_mode = std::ios_base::out | std::ios_base::app                      //追加输出
            );
    boost::shared_ptr<file_sink> sinkfrontNor = boost::make_shared<file_sink>(back_end_normal);     //前端绑定后端        
    sinkfrontNor->locked_backend()->set_file_collector(sinks::file::make_collector(                 //日志收集器设置
        keywords::target = logSubDir,
        keywords::max_files = MAX_BOOST_LOG_FILE_NUM
    ));
    sinkfrontNor->set_formatter(fmt);                       //设置格式
    sinkfrontNor->set_filter(trivials::severity >= trivials::debug);   //设置过滤器
    sinkfrontNor->locked_backend()->scan_for_files();       //扫描翻转文件夹使文件不重名
    logging::core::get()->add_sink(sinkfrontNor);           //添加到核心
    vec_sink_f.emplace_back(sinkfrontNor);                  //进管理队列

    //warning
    logSubDir = logDir + "/Warning";
    if (!filesys::exists(logSubDir))
        filesys::create_directories(logSubDir);

    boost::shared_ptr<sinks::text_file_backend> back_end_warning =
        boost::make_shared<sinks::text_file_backend>(
            keywords::file_name = "warning.log",
            keywords::target_file_name = "warning_%Y%m%d_%3N.log",
            keywords::rotation_size = 1024 * 1024 * 1024,                                       //
            keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0),      //每天0点翻转
            keywords::auto_flush = "true",                                                     //文件内容实时刷新
            keywords::open_mode = std::ios_base::out | std::ios_base::app                      //追加输出
            );
   
    boost::shared_ptr<file_sink> sinkfrontWarning = boost::make_shared<file_sink>(back_end_warning); //前端绑定后端
    sinkfrontWarning->locked_backend()->set_file_collector(sinks::file::make_collector(          //日志收集器设置
        keywords::target = logSubDir,
        keywords::max_files = MAX_BOOST_LOG_FILE_NUM
    ));
    sinkfrontWarning->locked_backend()->scan_for_files();       //扫描翻转文件夹使文件不重名
    sinkfrontWarning->set_formatter(fmt);                       //添加数据格式
    sinkfrontWarning->set_filter(trivials::severity >= trivials::warning);
    logging::core::get()->add_sink(sinkfrontWarning);
    vec_sink_f.emplace_back(sinkfrontWarning);                  //进管理队列

    //error
    logSubDir = logDir + "/error";
    if (!filesys::exists(logSubDir))
        filesys::create_directories(logSubDir);
    boost::shared_ptr<sinks::text_file_backend> back_end_error =
        boost::make_shared<sinks::text_file_backend>(
            keywords::file_name = "error.log",
            keywords::target_file_name = "error_%Y%m%d_%3N.log",
            keywords::rotation_size = 1024 * 1024 * 1024,
            keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0),
            keywords::auto_flush = "true",                                                     //文件内容实时刷新
            keywords::open_mode = std::ios_base::out | std::ios_base::app                      //追加输出
            );
    boost::shared_ptr<file_sink> sinkfrontError = boost::make_shared<file_sink>(back_end_error);
    sinkfrontError->locked_backend()->set_file_collector(sinks::file::make_collector(
        keywords::target = logSubDir,
        keywords::max_files = MAX_BOOST_LOG_FILE_NUM
    ));
    sinkfrontError->locked_backend()->scan_for_files();       //扫描翻转文件夹使文件不重名
    sinkfrontError->set_formatter(fmt);                       //添加数据格式
    sinkfrontError->set_filter(trivials::severity >= trivials::error);
    logging::core::get()->add_sink(sinkfrontError);
    vec_sink_f.emplace_back(sinkfrontError);                  //进管理队列

    //对消息添加属性，包括（线程ID、进程ID、时间戳等）
    logging::add_common_attributes();
    logging::core::get()->add_global_attribute("ThreadID", attrs::current_process_id());       //进程ID
    logging::core::get()->add_global_attribute("Process", attrs::current_thread_id());         //线程ID
    logging::core::get()->add_global_attribute("RecordID", attrs::counter<unsigned int>());    //记录ID
    logging::core::get()->add_global_attribute("Scope", attrs::named_scope());                 //记录行号，文件名

    return;
}

//syslog初始化
void CBoostLog::InitSysLog()
{
    boost::shared_ptr<sinks::syslog_backend> backend = boost::make_shared<sinks::syslog_backend>(
        keywords::facility = sinks::syslog::user);
        // keywords::use_impl = sinks::syslog::native);
        // keywords::use_impl = sinks::syslog::local1);

    //设置日志级别
    backend->set_severity_mapper(sinks::syslog::direct_severity_mapping<int>("Severity"));
   // boost::shared_ptr<sinks::synchronous_sink> sink_t = boost::make_shared<sinks::synchronous_sink>(backend);

    typedef sinks::synchronous_sink<sinks::syslog_backend> sink_t;
    logging::core::get()->add_sink(boost::make_shared<sink_t>(backend));
}

//停止日志系统
void CBoostLog::StopLog(void)
{
	if (isStoped)
		return;

    //文件流
    for (auto it : vec_sink_f)
        it.reset();

	isStoped = true;
}